EKS Auto Mode で Cilium をネットワークポリシーエンジンとして利用して、名前空間ごとに RDS アクセスを制限してみた
EKS Auto Mode を使うことで、ノードの管理を AWS にオフロードできるなど、多くのメリットがあります。
一方、現時点での制約として Pod の Security Group が使えないという物があります(2025 年 1 月時点)。
EKS Auto Mode does not support:
Security Groups per Pod (SGPP).
https://docs.aws.amazon.com/eks/latest/userguide/auto-networking.html
Network Policy を利用した Kubernetes 内の通信制御は可能ですが、RDS など AWS リソースとの通信制御時には少しやり辛さがあるかもしれません。
Network Policy でも IP ベースの通信制御は可能ですが、AWS リソースは IP が変更することを意識する必要があるケースが多いため、あまり使いやすい方法は言えません。
Pod のセキュリティグループを Network Policy と併用することで、Pod と AWS リソースの通信制御を行いやすくなります。ただし、Kubernetes 内の通信制御は Network Policy の方が扱いやすいので併用が推奨されます。
Network Policy and Security Groups for pod
By using a combination of security groups for pods and network policies, you can enhance your security posture. When network policy is enabled, security groups for pods serve as an additional layer in your defense-in-depth strategy. Network policies allow you to enforce granular controls over the flow of network traffic within your cluster whereas security groups for pods provides added protection by leveraging Amazon’s semantic controls to manage communications with resources within the Virtual Private Cloud (VPC), such as Amazon RDS databases. Amazon EKS strongly recommends employing network policies to restrict network communication between pods, thus reducing the attack surface and minimizing potential vulnerabilities. Please refer Amazon EKS Best Practices for complete guidance on using security groups alongside network policy.
https://aws.amazon.com/jp/blogs/containers/amazon-vpc-cni-now-supports-kubernetes-network-policies/
代替手段として DNS ベースで通信制御を行うことができる Cilium を利用することで、名前空間ごとに RDS への接続制御を行う方法を試してみました。
EKS Auto Mode は機能の一部として VPC CNI を提供しているため、今回はネットワークポリシーエンジンとしてのみ利用します。
With Amazon EKS Auto Mode, you don’t need to install or upgrade networking add-ons. Auto Mode includes pod networking and load balancing capabilities.
https://docs.aws.amazon.com/eks/latest/userguide/managing-vpc-cni.html
やってみる
v1.31 で Auto Mode を有効化した EKS を作成します。
作成手順は他記事で取り上げているので省略します。
マネジメントコンソールで作成したパターン。
eksctl で作成したパターン。
Terraform で作成したパターン。
Cilium を AWS VPC CNI plugin と併用する手順に沿ってインストールします。
リポジトリを追加します。
helm repo add cilium https://helm.cilium.io/
Cilium をインストールします。
helm install cilium cilium/cilium --version 1.14.18 \
--namespace kube-system \
--set cni.chainingMode=aws-cni \
--set cni.exclusive=false \
--set enableIPv4Masquerade=false \
--set routingMode=native \
--set endpointRoutes.enabled=true
無事、cilium-agent と cilium-operator が起動しました。
% kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
cilium-9vkdn 1/1 Running 0 3m59s
cilium-nhcks 1/1 Running 0 3m58s
cilium-operator-9f7574fd9-424rz 1/1 Running 0 4m19s
cilium-operator-9f7574fd9-xmbkw 1/1 Running 0 4m19s
名前空間を 2 つ作って、それぞれに CiliumNetworkPolicy を作成します。
kubectl create ns app1
kubectl create ns app2
app1 用の CiliumNetworkPolicy です。
こちらでのみ、RDS への接続を許可します。
名前空間内での通信や、名前解決用の通信は許可しておきます。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: app1-network-policy
namespace: app1
spec:
endpointSelector:
matchLabels: {}
ingress:
- fromEndpoints:
- matchLabels: {}
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": app1
- toFQDNs:
- matchPattern: "sample-aurora-postgres-cluster.cluster-xxxxxxx.ap-northeast-1.rds.amazonaws.com"
toPorts:
- ports:
- port: "5432"
protocol: TCP
- toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"
app2 用の CiliumNetworkPolicy です。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: app2-network-policy
namespace: app2
spec:
endpointSelector:
matchLabels: {}
ingress:
- fromEndpoints:
- matchLabels: {}
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": app2
- toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*"
app1 と app2 に Pod を作成して DB にアクセスさせてみます。
下記構成になります。
postgres コンテナを名前空間 app1 に起動して接続します。
% kubectl run postgres -it --rm --image=postgres:latest -n app1 /bin/bash
コンテナ内から、無事 RDS に接続できました。
root@postgres:/# psql -h $DB_HOST -U postgres
Password for user postgres:
psql (17.2 (Debian 17.2-1.pgdg120+1), server 16.4)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: none)
Type "help" for help.
postgres=>
app2 側にもコンテナを作成します。
% kubectl run postgres -it --rm --image=postgres:latest -n app2 /bin/bash
こちらから接続を試行した場合はタイムアウトになりました。
root@postgres:/# psql -h $DB_HOST -U postgres
psql: error: connection to server at "sample-aurora-postgres-cluster.cluster-xxxxxxx.ap-northeast-1.rds.amazonaws.com" (10.0.102.183), port 5432 failed: Connection timed out
Is the server running on that host and accepting TCP/IP connections?
無事通信を制御できていますね!
まとめ
EKS Auto Mode で Cilium を利用して、RDS との接続を制御してみました。
今後 EKS Auto Mode でも Pod のセキュリティグループを使えるようになる可能性はありますが、それまでは AWS リソースとの通信制御に有用ではないでしょうか!